#pragma once

template <typename Base>
struct Data
{
	static Base b;
	static size_t* pVTab;
	static Data& get(void*& pData)
	{
		if (!pData)
			pData = new Data(pData);

		return *reinterpret_cast<Data*>(pData);
	}

	void*& _pData = NULL;
	size_t _eventMax = 0;
	std::unordered_map<size_t, Base*> _funcMap;
	std::unordered_map<size_t, std::unordered_set<size_t>> _eventMap;

	Data(void*& pData) : _pData(pData) {}

	void add(size_t id)
	{
		Base* pData = sFactRepos.create<Base>(id);
		_funcMap[id] = pData;
		if (!_eventMax)
			return;

		size_t* tmpVTab = (size_t*)(*(size_t*)pData);
		for (size_t i = 0; i < _eventMax; ++i)
		{
			if (tmpVTab[i] != pVTab[i])
				_eventMap[i].insert(id);
		}
	}

	template <typename Func>
	void emit(size_t eventTy, Func func)
	{
		auto& evSet = _eventMap[eventTy];
		for (auto& funcId : evSet)
			func(_funcMap[funcId]);
	}

	void setEventMax(size_t max) { _eventMax = max; }
};

template <typename Base>
Base Data<Base>::b = Base();
template <typename Base>
size_t* Data<Base>::pVTab = (size_t*)(*(size_t*)&Data::b);